use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::IntoResponse,
    Extension, Json,
};
use tracing::info;

use crate::{
    models::{CreateChat, UpdateChat},
    AppState,
};
use chat_core::{error::AppError, User};

pub(crate) async fn list_chat_handler(
    Extension(user): Extension<User>,
    State(state): State<AppState>,
) -> Result<impl IntoResponse, AppError> {
    info!("user:{:?}", user);
    let chats = state.fetch_all_chats(user.ws_id as _).await?;
    Ok((StatusCode::OK, Json(chats)))
}

pub(crate) async fn create_chat_handler(
    Extension(user): Extension<User>,
    State(state): State<AppState>,
    Json(create_chat): Json<CreateChat>,
) -> Result<impl IntoResponse, AppError> {
    let create_chat = CreateChat::new(create_chat.name, create_chat.members, false);
    let chat = state
        .create_chat(&create_chat, user.ws_id, &user.fullname)
        .await?;
    Ok((StatusCode::OK, Json(chat)))
}
pub(crate) async fn update_chat_handler(
    Extension(user): Extension<User>,
    State(state): State<AppState>,
    Json(update_chat): Json<UpdateChat>,
) -> Result<impl IntoResponse, AppError> {
    state
        .update_chat(&update_chat, user.ws_id, &user.fullname)
        .await?;
    Ok((StatusCode::OK, "success".to_string()))
}

pub(crate) async fn delete_chat_handler(
    Extension(user): Extension<User>,
    State(state): State<AppState>,
    Path(chat_id): Path<i64>,
) -> Result<impl IntoResponse, AppError> {
    let chat_opt = state.fetch_chat_by_id(chat_id).await?;
    let chat = if let Some(chat) = chat_opt {
        chat
    } else {
        return Err(AppError::ChatNotFound(chat_id.to_string()));
    };
    if chat.ws_id != user.ws_id {
        return Err(AppError::NoPermission);
    }
    state.del_chat_by_id(chat_id).await?;
    Ok((StatusCode::OK, "success".to_string()))
}

pub(crate) async fn get_chat_handler(
    State(state): State<AppState>,
    Path(chat_id): Path<i64>,
) -> Result<impl IntoResponse, AppError> {
    let chat_opt = state.get_chat_by_id(chat_id).await?;
    let chat = if let Some(chat) = chat_opt {
        chat
    } else {
        return Err(AppError::ChatNotFound(chat_id.to_string()));
    };
    Ok((StatusCode::OK, Json(chat)))
}
